package nc

import (
	"time"

	"github.com/project-flogo/core/data/coerce"
)

// Settings trigger settings
type Settings struct {
	Network string `md:"network"`       // The network type
	Host    string `md:"host"`          // The host name or IP for TCP server.
	Port    string `md:"port,required"` // The port to listen on
	STX     string `md:"stx"`
	ETX     string `md:"etx"`
	Max     int    `md:"max"`
	Timeout string `md:"timeout"`
}

var (
	// OnAny run on any event
	OnAny = "ONANY"
	// OnData run on data received
	OnData = "ONDATA"
	// OnReconnect run on reconnecting
	OnReconnect = "ONRECONNECT"
	// OnConnected run on connected
	OnConnected = "ONCONNECTED"
	// OnError run on any error
	OnError = "ONERROR"
	// OnDisconnect run on disconnected
	OnDisconnect = "ONDISCONNECT"
	// OnClose run on close of client
	OnClose = "ONCLOSE"
	// OnReadTimeout run on reading timeout
	OnReadTimeout = "ONREADTIMEOUT"
	// OnPeerClose run on peer closed
	OnPeerClose = "ONPEERCLOSE"
)

// HandlerSettings handler settings
type HandlerSettings struct {
	Type string `md:"type,allowed(OnData,OnReconnect,OnConnected,OnError,OnDisconnect,OnClose,OnReadTimeout,OnPeerClose,OnAny)"`
}

// Output output data
type Output struct {
	Type                string    `md:"type"`
	Data                []byte    `md:"data"` // The data received from the connection
	LocalNetwork        string    `md:"localNetwork"`
	LocalAddr           string    `md:"localAddr"`
	RemoteNetwork       string    `md:"remoteNetwork"`
	RemoteAddr          string    `md:"remoteAddr"`
	TotalConnectedCount int       `md:"totalConnectedCount"`
	RecentRetryCount    int       `md:"recentRetryCount"`
	FirstConnectedTime  time.Time `md:"firstConnectedTime"`
	LastConnectedTime   time.Time `md:"lastConnectedTime"`
}

// Reply reply
type Reply struct {
	Reply []byte `md:"reply"` // The reply to be sent back
}

// ToMap output to map
func (o *Output) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"type":                o.Type,
		"data":                o.Data,
		"localNetwork":        o.LocalNetwork,
		"localAddr":           o.LocalAddr,
		"remoteNetwork":       o.RemoteNetwork,
		"remoteAddr":          o.RemoteAddr,
		"totalConnectedCount": o.TotalConnectedCount,
		"recentRetryCount":    o.RecentRetryCount,
		"firstConnectedTime":  o.FirstConnectedTime.Unix(),
		"lastConnectedTime":   o.LastConnectedTime.Unix(),
	}
}

// FromMap output from map
func (o *Output) FromMap(values map[string]interface{}) error {
	var err error

	o.Type, err = coerce.ToString(values["type"])
	if err != nil {
		return err
	}

	o.Data, err = coerce.ToBytes(values["data"])
	if err != nil {
		return err
	}

	o.LocalNetwork, err = coerce.ToString(values["localNetwork"])
	if err != nil {
		return err
	}

	o.LocalAddr, err = coerce.ToString(values["localAddr"])
	if err != nil {
		return err
	}

	o.RemoteNetwork, err = coerce.ToString(values["remoteNetwork"])
	if err != nil {
		return err
	}

	o.RemoteAddr, err = coerce.ToString(values["remoteAddr"])
	if err != nil {
		return err
	}

	o.TotalConnectedCount, err = coerce.ToInt(values["totalConnectedCount"])
	if err != nil {
		return err
	}

	o.RecentRetryCount, err = coerce.ToInt(values["recentRetryCount"])
	if err != nil {
		return err
	}

	t, err := coerce.ToInt64(values["firstConnectedTime"])
	if err != nil {
		return err
	}
	o.FirstConnectedTime = time.Unix(t, 0)

	t, err = coerce.ToInt64(values["lastConnectedTime"])
	if err != nil {
		return err
	}
	o.LastConnectedTime = time.Unix(t, 0)

	return nil
}

// ToMap Reply to map
func (r *Reply) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"reply": r.Reply,
	}
}

// FromMap reply from map
func (r *Reply) FromMap(values map[string]interface{}) error {

	var err error
	r.Reply, err = coerce.ToBytes(values["reply"])
	if err != nil {
		return err
	}

	return nil
}
